<?php

namespace App\Kuafu\Shop\Controller\Merchant;

use App\Exceptions\BaseException;
use App\Exceptions\CustomValidateException;
use App\Kuafu\Base\Controller\BaseController;
use App\Kuafu\Base\Enum\BaseCodeEnum;
use App\Kuafu\Config\Service\ConfigService;
use App\Kuafu\Shop\Enum\CodeEnum;
use App\Kuafu\Shop\Jobs\SyncCameraJob;
use App\Kuafu\Shop\Model\CameraModel;
use App\Kuafu\Shop\Service\CameraLibrary\CameraFactory;
use App\Kuafu\Shop\Service\CameraService;
use App\Kuafu\Shop\Service\DeviceService;
use App\Kuafu\Shop\Service\ShopService;
use App\Kuafu\Shop\Validate\DeviceValidate;
use App\Kuafu\User\Service\AuthService;
use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

/**
 * 摄像头
 */
class CameraController extends BaseController
{

    /**
     * 摄像机列表
     *
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     */
    public function index(Request $request): JsonResponse
    {
        $shopId = $this->shopId;
        $list   = CameraService::getCameraList($shopId);
        // 判断是否需要更新门店摄像头信息
        $shopInfo = ShopService::getShopInfo($shopId);

        if (!empty($shopInfo['cameraSupplierId']) && $shopInfo->cameraSupplier == CameraModel::SUPPLIER_YLK && count($list) === 0) {
            // 触发更新摄像头队列
            SyncCameraJob::dispatch($shopId)->onQueue(SyncCameraJob::$QUEUE_NAME);
        }

        // 校验限流
        CameraService::checkCameraLimit($shopInfo);

        if (count($list) > 0) {
            // 批量获取摄像头状态
            $first            = $list[0];
            $camera           = new CameraFactory($first->id);
            $cameraStatusList = $camera->getIns()->getDeviceStatusBatch($list->toArray());
            $cameraStatusList = array_column($cameraStatusList, null, 'id');

            foreach ($list as &$item) {
                $item['status'] = $cameraStatusList[$item['id']]['status'] ?? 0;
            }
        }

        return $this->success(['list' => $list]);
    }

    /**
     * 摄像机详情
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     * @return JsonResponse
     * @throws Exception
     */
    public function info(Request $request, int $shopId, int $id): JsonResponse
    {
        $camera     = new CameraFactory($id);
        $scheme     = $request->get('scheme', 'hls');
        $clarity    = CodeEnum::CLARITY_TYPE_HIGH_DEFINITION;
        $streamData = $camera->getIns()->getLiveStreaming($scheme, $clarity);

        $result = [
            'id'        => $camera->cameraInfo->id,
            'name'      => $camera->cameraInfo->name,
            'supplier'  => $camera->cameraInfo->supplier,
            'streamUrl' => $streamData['url'] ?? '',
            'time'      => time()
        ];

        return $this->success(['info' => $result]);
    }

    /**
     * 摄像机详情是否在线状态查询
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     * @return JsonResponse
     * @throws Exception
     */
    public function onlineStatus(Request $request, int $shopId, int $id): JsonResponse
    {
        $camera = new CameraFactory($id);
        $status = $camera->getIns()->getDeviceStatus();

        $result = [
            'id'       => $camera->cameraInfo->id,
            'name'     => $camera->cameraInfo->name,
            'isOnline' => $status
        ];

        return $this->success(['info' => $result]);
    }

    /**
     * 摄像机详情
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     * @return JsonResponse
     * @throws Exception
     */
    public function heartBeat(Request $request, int $shopId, int $id): JsonResponse
    {
        $camera = new CameraFactory($id);
        $type   = $request->get('type', '1');
        $scheme = $request->get('scheme', 'hls');
        $data   = $camera->getIns()->heartBeat($type, $scheme);

        return $this->success($data);
    }

    /**
     * 拍照接口
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     * @return JsonResponse
     */
    public function triggerCapturePicture(Request $request, int $shopId, int $id)
    {
        return $this->success();
//        $camera     = new CameraService($id);
//        $streamData = $camera->triggerCapturePicture();
//
//        $result = [
//            'id'          => $camera->cameraInfo->id,
//            'name'        => $camera->cameraInfo->name,
//            'pictureData' => $streamData
//        ];
//
//        return $this->success(['info' => $result]);
    }

    /**
     * 拍照接口
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     * @return JsonResponse
     */
    public function triggerCapturePictureDemo(Request $request)
    {
        return $this->success();

//        $pk = $request->get('pk');
//        $dn = $request->get('dn');
//
//        $camera = new CameraService();
//
//        $camera->cameraSdkService = new AliYunCamera($pk, $dn);
//
//        $streamData = $camera->cameraSdkService->triggerCapturePicture();
//
//        $result = [
//            'pictureData' => $streamData
//        ];
//
//
//        SendFs::newRobot(SendFs::ROBOT_BUSINESS_WARING)->setTitleContent('阿里云请求拍照接口', json_encode([
//            'requestParam' => [
//                'productKey' => $pk,
//                'deviceName' => $dn,
//            ],
//            'returnData'   => $result ?? [],
//        ]))->send();
//
//        return $this->success(['info' => $result]);
    }

    /**
     * 截图详情
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     * @param string $captureId
     * @return JsonResponse
     */
    public function queryDevicePictureFileDemo(Request $request)
    {
        return $this->success();

//        $pk                       = $request->get('pk');
//        $dn                       = $request->get('dn');
//        $cid                      = $request->get('cid');
//        $camera                   = new CameraService();
//        $camera->cameraSdkService = new AliYunCamera($pk, $dn);
//
//        $streamData = $camera->cameraSdkService->queryDevicePictureFile($cid);
//
//        $result = [
//            'pictureData' => $streamData
//        ];
//
//
//        SendFs::newRobot(SendFs::ROBOT_BUSINESS_WARING)->setTitleContent('阿里云请求截图详情', json_encode([
//            'requestParam' => [
//                'productKey' => $pk,
//                'deviceName' => $dn,
//                'cid'        => $cid
//            ],
//            'returnData'   => $result ?? [],
//        ]))->send();
//
//        return $this->success(['info' => $result]);
    }

    /**
     * 截图详情
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     * @param string $captureId
     * @return JsonResponse
     */
    public function queryDevicePictureFile(Request $request, int $shopId, int $id, string $captureId)
    {
        return $this->success();

//        $camera     = new CameraService($id);
//        $streamData = $camera->queryDevicePictureFile($captureId);
//
//        $result = [
//            'id'          => $camera->cameraInfo->id,
//            'name'        => $camera->cameraInfo->name,
//            'pictureData' => $streamData
//        ];
//
//        return $this->success(['info' => $result]);
    }

    /**
     * 开始录像
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     * @return JsonResponse
     */
    public function triggerRecord(Request $request, int $shopId, int $id)
    {
        return $this->success();
//        $camera = new CameraService($id);
//        if ($camera->cameraInfo->supplier == CameraModel::SUPPLIER_YLK) {
//            return $this->fail(0, '暂不支持此操作');
//        }
//        // 设置存储周期
//        $camera->setDeviceRecordLifeCycle();
//
//        $resultRequest = $camera->triggerRecord();
//
//        $result = [
//            'id'   => $camera->cameraInfo->id,
//            'name' => $camera->cameraInfo->name,
//            'data' => $resultRequest
//        ];
//
//        return $this->success(['info' => $result]);
    }

    /**
     * 结束录像
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     * @return JsonResponse
     */
    public function stopTriggeredRecord(Request $request, int $shopId, int $id)
    {
        return $this->success();
//        $camera        = new CameraService($id);
//        $recordId      = $request->get('recordId');
//        $resultRequest = $camera->stopTriggeredRecord($recordId);
//
//        if ($camera->cameraInfo->supplier == CameraModel::SUPPLIER_YLK) {
//            return $this->fail(0, '暂不支持此操作');
//        }
//
//        $result = [
//            'id'   => $camera->cameraInfo->id,
//            'name' => $camera->cameraInfo->name,
//            'data' => $resultRequest
//        ];
//
//        return $this->success(['info' => $result]);
    }

    /**
     * 调用该接口通过录像文件ID查询录像文件
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     */
    public function queryRecordByRecordId(Request $request, int $shopId, int $id)
    {
        return $this->success();
//        $camera = new CameraService($id);
//
//        $isDownload = $request->get('isDownload', 0);
//        $recordId   = $request->get('recordId');
//
//        $fileInfo = $camera->queryRecordByRecordId($recordId);
//
//        $downloadInfo = [];
//
//        if ($isDownload) {
//            $downloadInfo = $camera->queryRecordDownloadUrl($fileInfo['fileName']);
//        }
//
//        $result = [
//            'id'           => $camera->cameraInfo->id,
//            'name'         => $camera->cameraInfo->name,
//            'fileInfo'     => $fileInfo,
//            'downloadInfo' => $downloadInfo,
//        ];
//
//        return $this->success(['info' => $result]);
    }

    /**
     * 调用该接口通过文件名获取下载视频路径
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     */
    public function queryRecordDownloadUrlByFileName(Request $request, int $shopId, int $id)
    {
        return $this->success();
//
//        $camera = new CameraService($id);
//
//        $fileName = $request->get('fileName');
//
//        $downloadInfo = $camera->queryRecordDownloadUrl($fileName);
//
//        $result = [
//            'id'           => $camera->cameraInfo->id,
//            'name'         => $camera->cameraInfo->name,
//            'downloadInfo' => $downloadInfo,
//        ];
//
//        return $this->success(['info' => $result]);
    }

    /**
     * 调用该接口通过文件名获取下载视频路径
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     */
    public function queryRecordDownloadUrlByFileNameDemo(Request $request)
    {
        return $this->success();

//        $camera = new CameraService();
//
//        $fileName = $request->get('fileName');
//        $pk       = $request->get('pk');
//        $dn       = $request->get('dn');
//
//        $camera->cameraSdkService = new AliYunCamera($pk, $dn);
//
//        $result = $camera->cameraSdkService->queryRecordDownloadUrl($fileName);
//
//        SendFs::newRobot(SendFs::ROBOT_BUSINESS_WARING)->setTitleContent('阿里云请求下载接口', json_encode([
//            'requestParam' => [
//                'productKey' => $pk,
//                'deviceName' => $dn,
//            ],
//            'returnData'   => $result ?? [],
//        ]))->send();
//        return $this->success(['info' => $result]);
    }

    /**
     * 指定录像时间范围的录像文件播放地址。
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     * @return JsonResponse
     * @throws Exception
     */
    public function queryLocalRecordDate(Request $request, int $shopId, int $id): JsonResponse
    {
        $date   = $request->get('date', 0);
        $camera = new CameraFactory($id);
        $result = [
            'id'       => $camera->cameraInfo->id,
            'name'     => $camera->cameraInfo->name,
            'timeList' => $camera->getIns()->localVideoList(strtotime($date), strtotime($date) + 86400)
        ];

        return $this->success(['info' => $result]);
    }
//
//    /**
//     * 指定录像时间范围的录像文件播放地址。
//     *
//     * @param Request $request
//     * @param int $shopId
//     * @param int $id
//     * @return JsonResponse
//     */
//    public function queryDeviceVodUrlByTimeByInvokeDemo(Request $request)
//    {
//        $date = $request->get('date', 0);
//        $pk   = $request->get('pk');
//        $dn   = $request->get('dn');
//
//        $camera = new CameraService();
//
//        $camera->cameraSdkService = new AliYunCamera($pk, $dn);
//        $startAt                  = strtotime($date); // 开始时间
//        $endTime                  = $startAt + 86400; // 结束时间
//        $result                   = $camera->cameraSdkService->localVideoList($startAt, $endTime);
//
//        SendFs::newRobot(SendFs::ROBOT_BUSINESS_WARING)->setTitleContent('阿里云请求录像列表接口', json_encode([
//            'requestParam' => [
//                'productKey' => $pk,
//                'deviceName' => $dn,
//            ],
//            'returnData'   => $result ?? [],
//        ]))->send();
//
//        return $this->success(['timeList' => $result]);
//    }

    /**
     * 本地录像上云
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     */
    public function createLocalFileUploadJob(Request $request, int $shopId, int $id)
    {
        return $this->success();
//        $startAt = $request->get('startAt', 0);
//        $endAt   = $request->get('endAt', 0);
//
//        // 最大录制时间为 10 分钟
//        if ($endAt - $startAt > 600) {
//            $endAt = $startAt + 600;
//        }
//
//        $camera = new CameraService($id);
//
//        $camera->setDeviceRecordLifeCycle();
//
//        $result = [
//            'id'     => $camera->cameraInfo->id,
//            'name'   => $camera->cameraInfo->name,
//            'result' => $camera->createLocalFileUploadJob($startAt, $endAt)
//        ];
//        return $this->success(['info' => $result]);
    }

    /**
     * 本地录像上云
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     */
    public function createLocalFileUploadJobDemo(Request $request)
    {
        return $this->success();

//        $startAt = $request->get('startAt', 0);
//        $endAt   = $request->get('endAt', 0);
//        $pk      = $request->get('pk');
//        $dn      = $request->get('dn');
//
//        $camera = new CameraService();
//
//        $camera->cameraSdkService = new AliYunCamera($pk, $dn);
//        $camera->cameraSdkService->setDeviceRecordLifeCycle(7);
//
//        $result = $camera->cameraSdkService->createLocalFileUploadJob($startAt, $endAt);
//
//        SendFs::newRobot(SendFs::ROBOT_BUSINESS_WARING)->setTitleContent('阿里云请求本地录像上云接口', json_encode([
//            'requestParam' => [
//                'productKey' => $pk,
//                'deviceName' => $dn,
//            ],
//            'returnData'   => $result ?? [],
//        ]))->send();
//
//        return $this->success(['info' => $result]);


    }

    /**
     * 查询本地录像上传任务结果
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     */
    public function queryLocalFileUploadJobDemo(Request $request)
    {
        return $this->success();

//        $jobId                    = $request->get('jobId');
//        $pk                       = $request->get('pk');
//        $dn                       = $request->get('dn');
//        $camera                   = new CameraService();
//        $camera->cameraSdkService = new AliYunCamera($pk, $dn);
//
//        $result = $camera->cameraSdkService->queryLocalFileUploadJob($jobId);
//
//        SendFs::newRobot(SendFs::ROBOT_BUSINESS_WARING)->setTitleContent('阿里云请求本地录像上云接口', json_encode([
//            'requestParam' => [
//                'productKey' => $pk,
//                'deviceName' => $dn,
//            ],
//            'returnData'   => $result ?? [],
//        ]))->send();
//
//        return $this->success(['info' => $result]);
    }

    /**
     * 查询本地录像上传任务结果
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     */
    public function queryLocalFileUploadJob(Request $request, int $shopId, int $id)
    {
        return $this->success();
//        $jobId  = $request->get('jobId');
//        $camera = new CameraService($id);
//        $result = [
//            'id'     => $camera->cameraInfo->id,
//            'name'   => $camera->cameraInfo->name,
//            'result' => $camera->queryLocalFileUploadJob($jobId)
//        ];
//        return $this->success(['info' => $result]);
    }

    /**
     * 指定录像时间范围的录像文件播放地址。
     *
     * @param Request $request
     * @param int $shopId
     * @param int $id
     * @return JsonResponse
     * @throws Exception
     */
    public function queryDeviceVodUrlByTime(Request $request, int $shopId, int $id): JsonResponse
    {
        $startAt  = $request->get('startAt', 0);
        $endAt    = $request->get('endAt', 0);
        $seekTime = $request->get('seekTime', 0);
        $scheme   = $request->get('scheme', 'flv');

        $camera     = new CameraFactory($id);
        $streamData = $camera->getIns()->backUrl($startAt, $endAt, $seekTime, $scheme);

        $result = [
            'id'        => $camera->cameraInfo->id,
            'name'      => $camera->cameraInfo->name,
            'streamUrl' => $streamData['url']
        ];

        return $this->success(['info' => $result]);
    }

    /**
     * 获取表单配置
     *
     * @return JsonResponse
     * @throws BaseException
     */
    public function config(): JsonResponse
    {
        return $this->success(DeviceService::config());
    }

    /**
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     */
    public function shopTv(Request $request): JsonResponse
    {
        $shopId = $request->headers->get("shopId", 0);
        return $this->success(DeviceService::shopTv($shopId));
    }

    /**
     * 【电视机】- 设备绑定
     *
     * @param Request $request
     * @return JsonResponse
     * @throws CustomValidateException
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface|BaseException
     */
    public function bind(Request $request): JsonResponse
    {
        $params              = DeviceValidate::bindValidate(
            $request->merge(["shopId" => $request->headers->get("shopId")])->all()
        );
        $params->deviceType  = CameraModel::DEVICE_TYPE_TV;
        $params->queueSwitch = (int)$request->get('queueSwitch', 0); // 叫号次数
        $params->soundSwitch = (int)$request->get('soundSwitch', 0); // 声音开关
        $params->deviceName  = (int)$request->get('popPosition', 2); // 叫号弹窗方向 1 左 2 右 , 复用 dn 字段
        $params->productKey  = (int)$request->get('isQueueDevice', 0); // 是否叫号主设备 , 复用 pk 字段
        $params->bannerType  = (int)$request->get('bannerType', 0);
        $bannerIds           = (array)$request->get('bannerIds', []);

        $bannerMaxCount = ConfigService::getBannerMaxCount();
        if ($bannerIds && count($bannerIds) > $bannerMaxCount) {
            return $this->fail(BaseCodeEnum::ERR_400000, "最多选择{$bannerMaxCount}个广告");
        }

        $userId = AuthService::getUserId();
        DeviceService::bind($params, $userId, $bannerIds);
        return $this->success();
    }

    /**
     * 移除设备
     *
     * @param Request $request
     * @return JsonResponse
     * @throws ContainerExceptionInterface
     * @throws CustomValidateException
     * @throws NotFoundExceptionInterface
     */
    public function rmBind(Request $request): JsonResponse
    {
        $params = DeviceValidate::rmBindValidate(
            $request->merge([
                "shopId" => $request->headers->get("shopId")
            ])->all()
        );
        DeviceService::rmBind($params);
        return $this->success();
    }

    /**
     * @param Request $request
     * @return JsonResponse
     * @throws ContainerExceptionInterface
     * @throws CustomValidateException
     * @throws NotFoundExceptionInterface
     */
    public function deviceAdv(Request $request): JsonResponse
    {
        $params = DeviceValidate::deviceAdvValidate($request->all());

        $exist = Cache::remember('device:deviceAdv:cache:exist:' . $params->serialNo, 600, function () use ($params) {
            return CameraModel::query()->where("serialNo", $params->serialNo)->first();
        });
        if (empty($exist)) {
            return $this->fail(400000, '设备尚未绑定');
        }

        $data = Cache::remember('device:deviceAdv:cache:' . $params->serialNo, 8600, function () use ($params) {
            return DeviceService::deviceAdv($params->serialNo);
        });

        return $this->success($data);
    }

    /**
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     */
    public function bannerSearch(Request $request): JsonResponse
    {
        $type   = $request->get("type", 0);
        $shopId = $request->headers->get("shopId", 0);
        return $this->success(DeviceService::bannerSearch($shopId, $type));
    }

    /**
     * 设备详情
     * @param Request $request
     * @param int $id
     * @return JsonResponse
     */
    public function detail(Request $request, int $id): JsonResponse
    {
        $shopId = $request->headers->get("shopId", 0);
        return $this->success(DeviceService::detail($shopId, $id));
    }

    /**
     * 设备编辑
     * @param Request $request
     * @param int $id
     * @return JsonResponse
     */
    public function update(Request $request, int $id): JsonResponse
    {
        $this->validate($request, [
            'serialNo'      => 'required|string|size:16',
            'sort'          => "required|int|in:" . implode(',', array_keys(CameraModel::TV_POSITION_TEXT)),
            'queueSwitch'   => 'int|in:0,1,2,3,4,5',
            'soundSwitch'   => 'int|in:0,1',
            'popPosition'   => 'int|in:0,1,2', // 叫号弹窗方向 1 左 2 右 , 复用 dn 字段
            'isQueueDevice' => 'int|in:0,1', // 是否叫号主设备 , 复用 pk 字段
        ]);

        $shopId     = $request->headers->get("shopId", 0);
        $bannerIds  = (array)$request->get('bannerIds', []);
        $bannerType = (int)$request->get('bannerType', 0);

        $bannerMaxCount = ConfigService::getBannerMaxCount();
        if ($bannerIds && count($bannerIds) > $bannerMaxCount) {
            return $this->fail(BaseCodeEnum::ERR_400000, "最多选择{$bannerMaxCount}个广告");
        }

        $userId = AuthService::getUserId();
        DeviceService::update($request, $id, $shopId, $userId, $bannerType, $bannerIds);
        return $this->success();
    }

    /**
     * 广告位置查询是否系统配置了图片
     * @param Request $request
     * @return JsonResponse
     */
    public function bannerConfig(Request $request): JsonResponse
    {
        $this->validate($request, [
            'sort' => "required|int|in:" . implode(',', array_keys(CameraModel::TV_POSITION_TEXT)),
        ]);
        $shopId = $request->headers->get("shopId", 0);
        return $this->success(DeviceService::bannerConfig($request, $shopId));
    }

    /**
     * 广告素材组合单个搜索
     * @param Request $request
     * @param int $id
     * @return JsonResponse
     */
    public function bannerSearchById(Request $request, int $id): JsonResponse
    {
        $shopId = $request->headers->get("shopId", 0);
        return $this->success(DeviceService::bannerSearchById($id, $shopId));
    }
}
